/**
 * Copyright (c) 2008, Fabien Antoine
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

package fas.massload.file;

import flash.net.URLRequest;

import fas.massload.file.ILoadFile;

class LoadFileCreator
{
	//------------------------- //
	// Static private variables //
	//------------------------- //
	
	private static var LoaderExtensions:Array<String>		= [ "swf", "png", "gif", "jpg", "jpeg" ];
	
	private static var UrlLoaderExtensions:Array<String>		= [ "txt", "xml", "php", "asp" ];
	
	private static var SoundLoaderExtensions:Array<String>	= [ "mp3", "wav", "mod" ];
	
	
	//----------------------- //
	// Statics public methods //
	//----------------------- //
	
	/**
	 * Create an instance of ILoadFile
	 * @param		aFiles		Array			URL of the file
	 * @return					ILoadFile		Instance of an ULoadFile, LLoadFile, GLoadFile or SLoadFile
	 */
	public static function create( ?file:SingleFile, ?files:MultipleFile ):ILoadFile
	{
		if( file == null && files == null ) throw "You must enter at least one parameter";
		if( file != null && files != null ) throw "You must enter only one parameter";
		
		// If it's a single element, we detect its extension
		// Else if the multiple file contains more than 1 element, we create a group
		if( file != null )
		{
			// Trim the file name
			file.file = StringTools.trim( file.file );
			
			// Gets the extension
			var ext:String = getExtension( file.file );
			
			// Create the adequate LoadFile
			if( Lambda.has( LoaderExtensions, ext ) )
				return createLoader( file.file, file.name );
			else if( Lambda.has( UrlLoaderExtensions, ext ) )
				return createUrlLoader( file.file, file.name );
			else if( Lambda.has( SoundLoaderExtensions, ext ) )
				return createSoundLoader( file.file, file.name );
			else
				return null;
		}else if( files != null && files.files.length > 1 )
			return createGroupLoader( files );
		else
			return null;
	}
	
	
	/**
	 * Create an instance of ULoadFile
	 * @param		file		String			URL of the file
	 * @return				ILoadFile		Instance of an ULoadFile
	 */
	public static function createUrlLoader( sFile:String, sName:String ):ILoadFile
	{
		return new ULoadFile( new URLRequest( sFile ), sName );
	}		
	
	
	/**
	 * Create an instance of LLoadFile
	 * @param		file		String			URL of the file
	 * @return					ILoadFile		Instance of an LLoadFile
	 */
	public static function createLoader( sFile:String, sName:String ):ILoadFile
	{
		return new LLoadFile( new URLRequest( sFile ), sName );
	}
	
	/**
	 * Create an instance of SLoadFile
	 * @param		file		String			URL of the file
	 * @return					ILoadFile		Instance of an SLoadFile
	 */
	public static function createSoundLoader( sFile:String, sName:String ):ILoadFile
	{
		return new SLoadFile( new URLRequest( sFile ), sName );
	}
	
	
	/**
	 * Create an instance of GLoadFile
	 * @param		files		Array			Array of objects containing files URLs and names
	 * @return				ILoadFile		Instance of an GLoadFile
	 */
	public static function createGroupLoader( mFiles:MultipleFile ):ILoadFile
	{
		var group = new Array<ILoadFile>();
		
		for( i in 0...mFiles.files.length )
		{
			var elem:ILoadFile;
			
			// If the variable is a ILoadFile, we keep it
			// Else, we create it
			if( ( Std.is( mFiles.files[ i ], ILoadFile ) ) ) elem = mFiles.files[ i ];
			else if( Reflect.hasField( mFiles.files[ i ], "file" ) && Reflect.hasField( mFiles.files[ i ], "name" ) ) elem = create( mFiles.files[ i ] );
			else if( Reflect.hasField( mFiles.files[ i ], "files" ) && Reflect.hasField( mFiles.files[ i ], "name" ) ) elem = create( mFiles.files[ i ] );
			else elem = create( { file: mFiles.files[ i ], name: Std.string( mFiles.files[ i ] ) } );
			
			// And adds it if it's not null
			if( elem != null ) group.push( elem );
		}
		
		return new GLoadFile( group, mFiles.name );
	}
	
	
	/**
	 * Associate an extension to a ILoadFile type
	 * @param	fileType	String		LoadFile type to associate
	 * @param	ext		String		Extension to associate
	 */
	public static function addExtension( fileType:FileType, ext:String ) 
	{
		switch( fileType )
		{
			case Loader: 
				if( !Lambda.has( LoaderExtensions, ext ) ) LoaderExtensions.push( ext );
				
			case UrlLoader:
				if( !Lambda.has( UrlLoaderExtensions, ext ) ) UrlLoaderExtensions.push( ext );
				
			case SoundLoader:
				if( !Lambda.has( SoundLoaderExtensions, ext ) ) SoundLoaderExtensions.push( ext );
				
			default:
				throw "Impossible to add a new extension in type : " + Std.string( fileType );
		}
	}
	
	/**
	 * Extract the extension of a file name
	 * @param		sText		String			Name of a file
	 * @return					String			Extension of the file
	 */
	private static function getExtension( sText:String ):String
	{
		// We trim the text
		sText = StringTools.trim( sText );
		
		// If there's no text we return an empty string
		if( sText.length == 0 ) return "";
		
		// We get the extension
		return sText.substr( sText.lastIndexOf( "." ) + 1 ).toLowerCase();
	}
}

typedef SingleFile = {
	var file:String;
	var name:String;
}

typedef MultipleFile = {
	var files:Array<Dynamic>;
	var name:String;
}